#include "test.h"

#include <fenv.h>       /* fegetround, FE_* */
#include <math.h>       /* rint */

void show_all_except(void)  
{  
    //获取所有可能的异常  
    int res = fetestexcept(FE_ALL_EXCEPT);  
      
    printf( "Status: " );  
    if(res & FE_INEXACT)//判断是否有精度损失的异常  
    {  
        printf( " inexact ");  
    }  
    if(res & FE_UNDERFLOW)//判断是否有下溢  
    {  
        printf( " underflow ");  
    }  
    if(res & FE_OVERFLOW)//判断是否有上溢  
    {  
        printf( " overflow ");  
    }  
    if(res & FE_DIVBYZERO)//判断是否有被0除  
    {  
        printf( " zero-divide ");  
    }  
    if(res & FE_INVALID)//判断是否有不合法的浮点运算  
    {  
        printf( " invalid ");  
    }  
    printf( " \n ");  
}

void printfRounding(void)
{
    printf ("now rounding using: ");
    switch (fegetround()) {
        case FE_DOWNWARD: printf ("downward"); break;
        case FE_TONEAREST: printf ("to-nearest"); break;
        case FE_TOWARDZERO: printf ("toward-zero"); break;
        case FE_UPWARD: printf ("upward"); break;
        default: printf ("unknown");
    }
    printf("\n");
}

int fenv_test(int argc, char *argv[])
{
	fenv_t fe;
	printfRounding();//打印当前Rounding规则
	show_all_except();//打印当前异常状态
	fesetround(FE_TOWARDZERO);//设置Rounding规则为向0靠近
	feraiseexcept(FE_INEXACT);//注册一个精度丢失异常
	printfRounding();//重新打印当前Rounding规则
	show_all_except();//重新打印当前异常状态
	fegetenv(&fe);//获取当前浮点环境
	fesetenv(FE_DFL_ENV);//设置浮点环境为默认值
	printfRounding();//重新打印当前Rounding规则
	show_all_except();//重新打印当前异常状态
	fesetenv(&fe);//设置浮点环境为上次保存的浮点环境
	printfRounding();//重新打印当前Rounding规则
	show_all_except();//重新打印当前异常状态
	feraiseexcept(FE_OVERFLOW);//注册一个结果向上溢出异常
	feholdexcept(&fe);//保存当前浮点环境，并清除所有异常
	printfRounding();//重新打印当前Rounding规则
	show_all_except();//重新打印当前异常状态
	fesetenv(&fe);//设置浮点环境为上次保存的浮点环境
	printfRounding();//重新打印当前Rounding规则
	show_all_except();//重新打印当前异常状态
	return 0;
}
